package com.zhanggm.s3.house.controller;


import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageInfo;
import com.zhanggm.s3.core.pojo.LoginUser;
import com.zhanggm.s3.core.utils.AjaxResult;
import com.zhanggm.s3.core.utils.JwtUtils;
import com.zhanggm.s3.house.bo.EstateInfoBo;
import com.zhanggm.s3.house.elasticsearch.HouseRepository;
import com.zhanggm.s3.house.entity.Estate;
import com.zhanggm.s3.house.entity.Facility;
import com.zhanggm.s3.house.entity.House;
import com.zhanggm.s3.house.entity.HouseFacility;
import com.zhanggm.s3.house.service.IEstateService;
import com.zhanggm.s3.house.service.IFacilityService;
import com.zhanggm.s3.house.service.IHouseFacilityService;
import com.zhanggm.s3.house.service.IHouseService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.weaver.loadtime.Aj;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author zhanggm
 * @since 2023-07-21
 */
@Slf4j
@RestController
@RequestMapping("/house")
public class HouseController {

    @Autowired
    private IHouseService houseService;

    @Autowired
    private HouseRepository houseRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private IFacilityService facilityService;

    @Autowired
    private IHouseFacilityService houseFacilityService;

    @Autowired
    private IEstateService estateService;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;




    /**
     * 房源查询
     * @param house
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("page")
    public AjaxResult page(House house, Integer pageNum,Integer pageSize) {
        PageInfo<House> pageInfo = houseService.pageInfo(house,pageNum,pageSize);
        return AjaxResult.success(pageInfo);
    }

    /**
     * Es查询
     * @param house
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping("query")
    public AjaxResult query(House house, Integer pageNum,Integer pageSize) {
        //查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if (!StringUtils.isEmpty(house.getHouseType())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("houseType", house.getHouseType()));
        }
        if (!StringUtils.isEmpty(house.getHouseNumber())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("houseNumber", house.getHouseNumber()));
        }
        if (!StringUtils.isEmpty(house.getStructure())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("structure",house.getStructure()));
        }
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).build();
        //设置高亮
        String fieldToHighlight = "structure";
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .field(fieldToHighlight)
                .preTags("<em>")
                .postTags("</em>");
        HighlightQuery highlightQuery = new HighlightQuery(highlightBuilder);
        searchQuery.setHighlightQuery(highlightQuery);
        //查询数据
        SearchHits<House> search = elasticsearchRestTemplate.search(searchQuery, House.class);
        return AjaxResult.success(search);
    }

    /**
     * 房源保存
     * @param house
     * @return
     */
    @PostMapping("save")
    @DSTransactional
    public AjaxResult save(@RequestBody House house) {
        LoginUser curUserInfo = jwtUtils.getCurUserInfo(LoginUser.class);
        //防重复提交
        String lockKey = DigestUtil.md5Hex(curUserInfo.toString() + house.toString());
        if (!redisTemplate.opsForValue().setIfAbsent(lockKey, null, 3, TimeUnit.SECONDS)) {
            return AjaxResult.warn("请不要重复提交表单");
        }



        //保存房源
        houseService.saveOrUpdate(house);
        //保存配置设施,先删除关联的基础设施
        LambdaUpdateWrapper<HouseFacility> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(HouseFacility::getHouseId, house.getHouseId());
        houseFacilityService.remove(wrapper);
        //批量插入数据
        List<Integer> facilityIdList = house.getFacilityIdList();
        if (facilityIdList != null) {
            List<HouseFacility> saveList = new ArrayList<>();
            facilityIdList.forEach(item->{
                HouseFacility houseFacility = new HouseFacility(house.getHouseId(), item);
                saveList.add(houseFacility);
            });
            houseFacilityService.saveBatch(saveList);
        }
        if (house.getHouseType().equals("123")) {
            throw new RuntimeException();
        }

        return AjaxResult.success();
    }

    /**
     * 房源更新初始化数据接口
     * @param id
     * @return
     */
    @GetMapping("update/init")
    public AjaxResult init(Integer id) {
        Map<String, Object> result = new HashMap<>();
        //如果编辑页面，根据Id，查询房源信息
        if (id != null) {
            House house = houseService.getById(id);
            result.put("house", house);
            //查询选中的房源设施名称
            LambdaQueryWrapper<HouseFacility> query = new LambdaQueryWrapper<>();
            query.eq(HouseFacility::getHouseId, id);
            List<HouseFacility> houseFacilityList = houseFacilityService.list(query);
            List<Integer> facilityIdList = houseFacilityList.stream().map(item -> item.getFacilityId()).collect(Collectors.toList());
            result.put("facilityIdList", facilityIdList);
        }
        //查询楼盘信息
        List<Facility> facilityList = facilityService.list();
        result.put("facilityList", facilityList);
        //查询楼盘信息
        List<Estate> estateList = estateService.list();
        result.put("estateList", estateList);

        return AjaxResult.success(result);
    }

    /**
     * 审核
     * @param houseId
     * @return
     */
    @GetMapping("check")
    public AjaxResult check(Integer houseId) {
        LoginUser curUserInfo = jwtUtils.getCurUserInfo(LoginUser.class);
        House house = houseService.getById(houseId);
        if (!house.getStatus().equals(0)) {
            return AjaxResult.success("该房源已审核");
        }
        if (!curUserInfo.getRoleCode().equals("admin")) {
            return AjaxResult.success("只有管理员才能审核房源");
        }
        //修改房源状态
        house.setStatus(1);
        houseService.saveOrUpdate(house);
        return AjaxResult.success("审核通过，可以发布了");
    }


    /**
     * 房源发布
     * @param houseId
     * @return
     */
    @GetMapping("pulished")
    public AjaxResult pulished(Integer houseId) {
        House house = houseService.getById(houseId);
        house.setStatus(2);
        //修改房源状态
        houseService.saveOrUpdate(house);
        //增量同步Es
        PageInfo<House> housePageInfo = houseService.pageInfo(new House().setHouseId(houseId), 1, 1);
        House esHouse = housePageInfo.getList().get(0);
        houseRepository.save(esHouse);
        return AjaxResult.success();
    }


    /**
     * Es全量同步
     * @return
     */
    @GetMapping("all")
    public AjaxResult sync() {
        log.info("开始全量同步房源数据");
        int pageSize = 100;
        int pageNum = 1;
        while (true) {
            PageInfo<House> housePageInfo = houseService.pageInfo(null, pageNum, pageSize);
            if (housePageInfo.getList() == null || housePageInfo.getList().size() == 0) {
                break;
            }
            Iterable<House> houses = houseRepository.saveAll(housePageInfo.getList());
            houses.forEach(item->{
                log.info(item.toString());
            });
            pageNum++;
        }
        log.info("同步完成");
        return AjaxResult.success("同步数据成功");
    }

}
